package com.hc.java.io.nio;

import java.io.*;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;

/**
 * @author huangchao E-mail:fengquan8866@163.com
 * @version 创建时间：2024/8/30 10:57
 */
public class MmapNIO {
    public static void main(String[] args) throws IOException {
        // 1.通过File类定义要操作的文件路径，因为此时要使用的是FileOutputStream类，这个类需要File
        File file = new File("E:\\tmp\\1.txt");
        // 2.如果熬进行文件内容的输出，则一定要首先创建对应的父目录
        if (!file.exists()) {
            System.out.println("文件路径不存在："+file);
            System.exit(1);
        }
//        read(file);
        rw(file);
    }

    private static void rw(File file) throws IOException {
        // 3、读写 最佳 RandomAccessFile类
        RandomAccessFile raf = new RandomAccessFile(file, "rw"); // 使用读写模式
        // 4、RandomAccessFile类中提供了getChannel()方法，直接调用它获取FileChannel的对象实例
        FileChannel channel = raf.getChannel(); // 具备读写支持
        // 5、内存映射处理
        MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_WRITE, 50, 60);
        byte[] data = new byte[60]; // 定义字节数组，长度 = 映射的长度
        int foot = 0; // 字节数组操作角标
        while (buffer.hasRemaining()) {
            data[foot++] = buffer.get();
        }
        System.out.println("【文件内容】" + new String(data));
        // 6、对缓冲区进行数据的添加
        buffer.clear(); // 清空缓冲区数据
        buffer.put("俺的-----------------------------".getBytes()); // 通过映射设置内容
        // 7、关闭通道
        channel.close();
    }

    private static void read(File file) throws IOException {
        // 3、如果要找到FileChannel类的对象实例，就必须实例化FileInputStream
        FileInputStream input = new FileInputStream(file);// 不要转型为InputStream
        // 4、找到FileChannel类的对象，由于此时是文件输出流，所以该Channel为输出通道
        FileChannel channel = input.getChannel(); // 如果要进行MMap的处理，那么必须用药有文件通道
        // 5、通过FileChannel类中定义的map()处理方法到内存映射
        MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, file.length());// 对整个的文件映射
        // 6、此时数据已经进行了映射，那么这个时候就属于用户进程的处理操作了，直接定义个数组
        // 如果觉得此时字节数组的使用不方便，可以使用ByteArrayOutputStream内存输出流进行处理
        byte[] data = new byte[(int) file.length()]; // 直接开辟字节数组
        int foot = 0; // 定义一个数组的操作角标
        while (buffer.hasRemaining()) {
            data[foot++] = buffer.get();
        }
        System.out.println("【文件内容】" + new String(data));
        // 7、关闭
        channel.close();
    }
}
